pub mod alloc;
pub mod asm;
pub mod panic;

pub mod lock {
    use core::sync::atomic::{spin_loop_hint, AtomicBool, Ordering};
    pub struct SpinLock {
        status: AtomicBool,
    }

    impl SpinLock {
        pub const fn new() -> SpinLock {
            SpinLock {
                status: AtomicBool::new(false),
            }
        }

        pub fn lock(&mut self) {
            while self.status.compare_and_swap(false, true, Ordering::SeqCst) {
                spin_loop_hint();
            }
        }

        pub fn unlock(&mut self) {
            assert!(self.status.load(Ordering::SeqCst));
            self.status.store(false, Ordering::SeqCst);
        }
    }
}

#[no_mangle]
pub extern "C" fn die() -> ! {
    // use write! to catch double_fault
    write!(get_serial(), "[INFO ] die() called\n\r").unwrap_or_else(|_| {
        double_fault();
    });
    loop {
        unsafe {
            asm::hlt();
        }
    }
}

pub fn double_fault() -> ! {
    loop {
        unsafe {
            asm::hlt();
        }
    }
}

const fn null<T>() -> *const T {
    0 as *const T
}

const fn null_mut<T>() -> *mut T {
    0 as *mut T
}
